﻿local Addon_name, TGJAN = ...

-- $Id: InitWoWPro.lua 203 2010-02-09 23:32:49Z eric.beaudoin $

if not WoWPro or TGJAN.NoWoWPro then return end

--==============================================================--
--   Take the guides' |U| before GetQuestLogSpecialItemInfo     --
--==============================================================--

WoWPro.UpdateStatusFrame = nil
function WoWPro:UpdateStatusFrame()
   local dataobj = LibStub:GetLibrary("LibDataBroker-1.1"):GetDataObjectByName("WoWPro")
	self:Debug(1, "UpdateStatusFrame", self.current)

	if self.updatedelay then
		local _, logi = self:GetObjectiveStatus(self.updatedelay)
		self:Debug(1, "Delayed update", self.updatedelay, logi)
		if logi then return end
	end

	local nextstep
	self.updatedelay = nil

	for i in ipairs(self.actions) do
		local turnedin, logi, complete = self:GetObjectiveStatus(i)
		if not turnedin and not nextstep then
			local action, name, quest = self:GetObjectiveInfo(i)
			local note, useitem, optional, prereq, lootitem, lootqty = self:GetObjectiveTag("N", i), self:GetObjectiveTag("U", i), self:GetObjectiveTag("O", i), self:GetObjectiveTag("PRE", i), self:GetObjectiveTag("L", i)
			self:Debug(11, "UpdateStatusFrame", i, action, name, note, logi, complete, turnedin, quest, useitem, optional, lootitem, lootqty, lootitem and GetItemCount(lootitem) or 0)
			local hasuseitem = useitem and self:FindBagSlot(useitem)
			local haslootitem = lootitem and GetItemCount(lootitem) >= lootqty
			local prereqturnedin = prereq and self.turnedin[prereq]

			-- Test for completed objectives and mark them done
			if action == "SETHEARTH" and self.db.char.hearth == name then return self:SetTurnedIn(i, true) end

			local zonetext, subzonetext, subzonetag = GetZoneText(), string.trim(GetSubZoneText()), self:GetObjectiveTag("SZ")
			if (action == "RUN" or action == "FLY" or action == "HEARTH" or action == "BOAT") and (subzonetext == name or subzonetext == subzonetag or zonetext == name or zonetext == subzonetag) then return self:SetTurnedIn(i, true) end

			if action == "KILL" or action == "NOTE" then
				if not optional and haslootitem then return self:SetTurnedIn(i, true) end

				local quest, questtext = self:GetObjectiveTag("Q", i), self:GetObjectiveTag("QO", i)
				if quest and questtext then
					local qi = self:GetQuestLogIndexByName(quest)
					for lbi=1,GetNumQuestLeaderBoards(qi) do
						self:Debug(1, quest, questtext, qi, GetQuestLogLeaderBoard(lbi, qi))
						if GetQuestLogLeaderBoard(lbi, qi) == questtext then return self:SetTurnedIn(i, true) end
					end
				end
			end

			local incomplete
			if action == "ACCEPT" then incomplete = (not optional or hasuseitem or haslootitem or prereqturnedin) and not logi
			elseif action == "TURNIN" then incomplete = not optional or logi
			elseif action == "COMPLETE" then incomplete = not complete and (not optional or logi)
			elseif action == "NOTE" or action == "KILL" then incomplete = not optional or haslootitem
			else incomplete = not logi end

			if incomplete then nextstep = i end

			if action == "COMPLETE" and logi and self.db.char.trackquests then
				local j = i
				repeat
					action = self:GetObjectiveInfo(j)
					turnedin, logi, complete = self:GetObjectiveStatus(j)
					if action == "COMPLETE" and logi and not complete then AddQuestWatch(logi) -- Watch if we're in a 'COMPLETE' block
					elseif action == "COMPLETE" and logi then RemoveQuestWatch(logi) end -- or unwatch if done
					j = j + 1
				until action ~= "COMPLETE"
			end
		end
	end
	QuestLog_Update()
	WatchFrame_Update()

	if not nextstep and self:LoadNextGuide() then return self:UpdateStatusFrame() end
	if not nextstep then return end

	self.current = nextstep
	local action, quest, fullquest = self:GetObjectiveInfo(nextstep)
	local turnedin, logi, complete = self:GetObjectiveStatus(nextstep)
	local note, useitem, optional = self:GetObjectiveTag("N", nextstep), self:GetObjectiveTag("U", nextstep), self:GetObjectiveTag("O", nextstep)

	dataobj.text, dataobj.icon = (quest or"???")..(note and " [?]" or ""), self.icons[action]
	SendAddonMessage("WoW-Pro", action.." "..(quest or "???"), "PARTY")

	self:DebugF(1, "Progressing to objective \"%s %s\"", action, quest)

	-- Mapping
--	if (TomTom or Cartographer_Waypoints) and (lastmapped ~= quest or lastmappedaction ~= action) then
--		lastmappedaction, lastmapped = action, quest
		self:ParseAndMapCoords(action, quest, self:GetObjectiveTag("Z", nextstep) or self.zonename, note, self:GetObjectiveTag("QID", nextstep))
--	end

	if self.db.char.showuseitem and action == "COMPLETE" and self.db.char.showuseitemcomplete then
		local useitem2, tex2 = GetQuestLogSpecialItemInfo(logi or 0)
		useitem2, tex2 = GetQuestLogSpecialItemInfo(logi or 0)
		if useitem2 then useitem2 = tonumber(useitem2:match("item:(%d+):")) end
		self:SetUseItem((useitem and select(10, GetItemInfo(tonumber(useitem))) or tex2), useitem or useitem2)
	elseif self.db.char.showuseitem and action ~= "COMPLETE" then
		self:SetUseItem(useitem and select(10, GetItemInfo(tonumber(useitem))), useitem)
	else
		self:SetUseItem()
	end

	self:UpdateOHPanel()
	self:UpdateGuidesPanel()
end


--==========================================================--
--            Display the tooltip on the use button         --
--==========================================================--

do
	local frame = _G["WoWProItemFrame"]
	local item

	frame:HookScript("OnEnter", function (self) --item:16846:0:0:0:0:0:0:0
		GameTooltip:SetOwner(self); GameTooltip:SetHyperlink("item:"..item); GameTooltip:Show();
	end);
	frame:HookScript("OnLeave", GameTooltip_Hide);
	
	local old_SetUseItem = WoWPro.SetUseItem
	
	local function SetUseItem(self, tex, use)
		item = use
		return old_SetUseItem(self, tex, use)
	end
	WoWPro.SetUseItem = SetUseItem
end 

--==========================================================--
--     Map from notes instead of LightHeaded if present     --
--        Refresh maped POI on each quest log update        --
--==========================================================--

do

	local L = WoWPro.Locale

	local zonei, zonec, zonenames = {}, {}, {}
	for ci,c in pairs{GetMapContinents()} do
		zonenames[ci] = {GetMapZones(ci)}
		for zi,z in pairs(zonenames[ci]) do
			zonei[z], zonec[z] = zi, ci
		end
	end


	local cache = {}
	local function MapPoint(zone, x, y, desc, c, z)
		WoWPro:DebugF(1, "Mapping %q - %s (%.2f, %.2f)", desc, zone or z, x, y)
		local zi, zc = z or zone and zonei[zone], c or zone and zonec[zone]
		if not zi then
			if zone then WoWPro:PrintF(L["Cannot find zone %q, using current zone."], zone)
			else WoWPro:Print(L["No zone provided, using current zone."]) end

			zi, zc = GetCurrentMapZone(), GetCurrentMapContinent()
		end
		zone = zone or zonenames[zc][zi]

		if TomTom then 
			local wpid = TomTom:AddZWaypoint(zc, zi, x, y, desc, false)
			table.insert(cache, wpid)
			return wpid
		elseif Cartographer_Waypoints then
			local pt = NotePoint:new(zone, x/100, y/100, desc)
			Cartographer_Waypoints:AddWaypoint(pt)
			table.insert(cache, pt.WaypointID)
			return pt.WaypointID
		end
	end


	local tries = 0
	local elapsed = 0
	local taction, tquest, tzone, tnote, tqid, tlogi
	local f = CreateFrame("Frame")
	f:Hide()
	f:SetScript("OnShow", 
					function() 
--geterrorhandler()(format("Show: %d", elapsed))
						elapsed = 0 
	end)
	f:SetScript("OnUpdate", function(self, elap)
		elapsed = elapsed + elap
		if elapsed < 1 then return end
		self:Hide()
		WoWPro:ParseAndMapCoords(taction, tquest, tzone, tnote, tqid, tlogi, true)
--geterrorhandler()(format("Update: %s, %s, %s, %s, %s, %s",taction, tquest or 'nil', tzone or 'nil' , tnote or 'nil' , tqid or -1, tlogi or 'nil'))
	end)

	local temp = {}
	WoWPro.ParseAndMapCoords = nil
	function WoWPro:ParseAndMapCoords(action, quest, zone, note, qid, logi, timer)
--geterrorhandler()(format("Parse: %s, %s, %s, %s, %s, %s",taction or 'nil', tquest or 'nil', tzone or 'nil' , tnote or 'nil' , tqid or -1, tlogi or 'nil'))
		taction, tquest, tzone, tnote, tqid, tlogi = action, quest, zone, note, qid, logi
	
		if not timer then
			if TomTom and TomTom.RemoveWaypoint then
				while cache[1] do TomTom:RemoveWaypoint(table.remove(cache)) end
			elseif Cartographer_Waypoints then
				while cache[1] do Cartographer_Waypoints:CancelWaypoint(table.remove(cache)) end
			end
		end

		local questtext = self:GetObjectiveTag("QO")
		local nopoi = self:GetObjectiveTag("NOPOI")
		local found_poi = false
		WoWPro:Debug(10,"ParseAndMapCoords", nopoi, action, logi, questtext)
		if (not nopoi and qid and (action == "COMPLETE" or action == "TURNIN" or questtext)) then
			if WoWPro:MapPOI(action,qid) then
				tries = 0
				found_poi = true
			else
				tries = tries + 1
				if tries <= 5 then 
					f:Show() 
				else
					tries = 0
				end
			end
		end

		if timer or found_poi then return end -- only do the "hardcoded" coordinate once 
		note = note or ''
		if self.db.char.mapnotecoords then 
			for x,y in note:gmatch(L.COORD_MATCH) do table.insert(temp, tonumber(y)); table.insert(temp, tonumber(x)) end
		end
		if (action == "ACCEPT" or action == "TURNIN") and #temp == 0 then self:MapLightHeadedNPC(qid, action, quest) end
		while temp[1] do MapPoint(zone, table.remove(temp), table.remove(temp), "[TG] "..(questtext or quest)) end
	end
	
	WoWPro.QUEST_LOG_UPDATE = nil
	function WoWPro:QUEST_LOG_UPDATE(event)
--geterrorhandler()(format("Event: %s",event))
		self:QuestID_QUEST_LOG_UPDATE()

		local action, _, logi, complete = self:GetObjectiveInfo(), self:GetObjectiveStatus()
		self:Debug(10, "QUEST_LOG_UPDATE", action, logi, complete)

		if (self.updatedelay and not logi) or action == "ACCEPT" or action == "COMPLETE" and complete then self:UpdateStatusFrame() end

		if action == "KILL" or action == "NOTE" then
			if complete then self:UpdateStatusFrame() end
			if self:GetObjectiveTag("QID") then return end

			local quest, questtext = self:GetObjectiveTag("Q"), self:GetObjectiveTag("QO")
			if not quest or not questtext then return end

			local qi = self:GetQuestLogIndexByName(quest)
			if qi and questtext and self:IsQuestObjectiveComplete(qi, questtext) then self:SetTurnedIn() end
		end
		
		WoWPro:MapPOI(action)
	end

	local currentPOI = nil
	function WoWPro:MapPOI(action,qid) 
		action = action or self.actions[self.current]
		
		if currentPOI then
			if TomTom and TomTom.RemoveWaypoint then
				TomTom:RemoveWaypoint(currentPOI)
				currentPOI = nil
			elseif Cartographer_Waypoints then
				Cartographer_Waypoints:CancelWaypoint(currentPOI) 
			end
		end
		
		if action ~= "COMPLETE" and action ~= "TURNIN" and not self:GetObjectiveTag("QO") then return false end
		
		local qid = qid or self:GetObjectiveTag("QID")
		local nopoi = self:GetObjectiveTag("NOPOI")
		
		if not nopoi and qid then
			QuestMapUpdateAllQuests()
			QuestPOIUpdateIcons()
			local _, x, y, obj = QuestPOIGetIconInfo(qid)
			if x and y then
				local zone = self:GetObjectiveTag("Z") or self.zonename
				local questTitle, questID, i = '', nil, 1
				while questID ~= qid and i <= GetNumQuestLogEntries() do
					questTitle, _, _, _, _, _, _, _, questID = GetQuestLogTitle(i)
					i = i + 1
				end
				if questID == qid then
					local npc = ''
					if action == "TURNIN" and LightHeaded and LightHeaded.GetQuestInfo then
						npc = select(9,LightHeaded:GetQuestInfo(qid))
						if npc then npc = " ("..npc..")" end
					end
					currentPOI = MapPoint(zone, x*100, y*100, "[POI] "..questTitle..npc)
					return true
				end
			end
		end
		
		return false
	end

	WoWPro.MapLightHeadedNPC = nil
	function WoWPro:MapLightHeadedNPC(qid, action, quest)
	--geterrorhandler()(format("WoW-Pro: qid=%s, action=%s, quest=%s",qid, action, quest))
		if not self.db.char.mapquestgivers then return end

		local npcid, npcname, stype
		if action == "ACCEPT" then _, _, _, _, stype, npcname, npcid = LightHeaded:GetQuestInfo(qid)
		else _, _, _, _, _, _, _, stype, npcname, npcid = LightHeaded:GetQuestInfo(qid) end
		self:Debug(1, "LightHeaded lookup", action, qid, stype, npcname, npcid)

		if stype ~= "npc" then return end

		local data = LightHeaded:LoadNPCData(tonumber(npcid))
		if not data then return end
		for zid,x,y in data:gmatch("([^,]+),([^,]+),([^:]+):") do MapPoint(nil, tonumber(x), tonumber(y), "[LH] "..quest.." ("..npcname..")", LightHeaded:WZIDToCZ(tonumber(zid))) end
		return true
	end

end


--==============================================================--
--     Use GetQuestsCompleted to refresh the guides' quests     --
--==============================================================--

do 

	local completedquests = {}

	WoWPro.QUEST_QUERY_COMPLETE = nil
	function WoWPro:QUEST_QUERY_COMPLETE()
		GetQuestsCompleted(completedquests)
		-- Set the completed quests as completed for TourGuide
		for qid in pairs(completedquests) do WoWPro.turnedinquests[qid] = true end 
		-- if a quest was marked complete, it stays completed
		local function helper(...)
			for i=1,select("#", ...) do
				local val = tonumber((select(i, ...)))
				if val then WoWPro.turnedinquests[val] = true end
			end
		end
		helper(string.split(",", TGJANQuestHistoryDB or ""))
		
		self:UpdateStatusFrame()
	end

end